package com.open.anim.animator;

import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.view.View;
import android.view.animation.Interpolator;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 基本动画抽象类
 */
public abstract class BaseAnimator {

    public static final long DEFUALT_DURATION = 300;
    AnimatorSet.Builder animSetBuilder;
    private AnimatorSet mAnimatorSet;
    private Interpolator mInterpolator;
    TypeEvaluator mTypeEvaluator;
    private long mDuration = -1;
    private long mStartDelay = 0;
    private int mRepeatCount = 0;
    private int mRepeatMode = ValueAnimator.RESTART;
    private boolean mIsTogether = false;

    public BaseAnimator() {
        mAnimatorSet = new AnimatorSet();
    }

    /**
     * 在 AnimSet的基础下，加上各种动画效果组合
     */
    public abstract void prepareAnimSet();

    public BaseAnimator play(BaseAnimator item) {
        item.prepareAnimSet();
        getAnimatorList(item); // 设置传入的item各个属性(比如延时，耗时，targe view)
        animSetBuilder = mAnimatorSet.play(item.getAnimatorSet());
        return this;
    }

    /**
     * 获取动画的集合
     */
    public AnimatorSet getAnimatorSet() {
        return mAnimatorSet;
    }

    public BaseAnimator before(BaseAnimator item) {
        if (null == animSetBuilder) {
            animSetBuilder = mAnimatorSet.play(null);
        }
        item.prepareAnimSet();
        getAnimatorList(item); // 设置传入的item各个属性(比如延时，耗时，targe view)
        animSetBuilder.before(item.getAnimatorSet());
        return this;
    }

    public BaseAnimator after(BaseAnimator item) {
        if (null == animSetBuilder) {
            animSetBuilder = mAnimatorSet.play(null);
        }
        item.prepareAnimSet();
        getAnimatorList(item); // 设置传入的item各个属性(比如延时，耗时，targe view)
        animSetBuilder.after(item.getAnimatorSet());
        return this;
    }

    public BaseAnimator with(BaseAnimator item) {
        if (null == animSetBuilder) {
            animSetBuilder = mAnimatorSet.play(null);
        }
        item.prepareAnimSet();
        getAnimatorList(item); // 设置传入的item各个属性(比如延时，耗时，targe view)
        animSetBuilder.with(item.getAnimatorSet());
        return this;
    }

    /**
     * 并行执行动画 res/anim xml(属性动画) 集合
     */
    public BaseAnimator playTogether(Context context, int... items) {
        mIsTogether = true;
        List<Animator> animatorList = getAnimatorList(context, items);
        if (null != animatorList && animatorList.size() > 0) {
            mAnimatorSet.playTogether(animatorList);
        }
        return this;
    }

    private List<Animator> getAnimatorList(Context context, int... items) {
        List<Animator> animatorList = new ArrayList<>();
        if (null != items && null != context) {
            for (int i = 0; i < items.length; ++i) {
                int item = items[i];
                Animator animator = AnimatorInflater.loadAnimator(context.getApplicationContext(), item);
                animatorList.add(animator);
            }
        }
        return animatorList;
    }

    /**
     * 并行执行动画集合
     */
    public BaseAnimator playTogether(BaseAnimator... items) {
        mIsTogether = true;
        List<Animator> animatorList = getAnimatorList(items);
        if (null != animatorList && animatorList.size() > 0) {
            mAnimatorSet.playTogether(animatorList);
        }
        return this;
    }

    private List<Animator> getAnimatorList(BaseAnimator... items) {
        List<Animator> animatorList = new ArrayList<>();
        if (items != null) {
            for (int i = 0; i < items.length; ++i) {
                BaseAnimator anim = items[i];
                anim.prepareAnimSet();
                // 容错处理
                AnimatorSet animatorSet = anim.getAnimatorSet();
                if (null == animatorSet) {
                    continue;
                }
                // target view
                if (null != anim.getTarget()) {
                    animatorSet.setTarget(anim.getTarget());
                }
                // 设置耗时
                if (anim.getDuration() > 0) {
                    animatorSet.setDuration(anim.getDuration());
                }
                // 设置延时
                if (anim.getStartDelay() > 0) {
                    animatorSet.setStartDelay(anim.getStartDelay());
                }
                // 递归设置 TypeEvaluator 属性
                if (null != anim.getAnimatorSet().getChildAnimations()) {
                    initAllAnimTypeEvaluator(anim, anim.getAnimatorSet());
                }
                animatorList.add(anim.getAnimatorSet());
            }
        }
        return animatorList;
    }

    /**
     * 递归设置 TypeEvaluator 属性
     *
     * @param anim BaseAnimator
     * @param animatorSet AnimatorSet
     */
    private void initAllAnimTypeEvaluator(BaseAnimator anim, AnimatorSet animatorSet) {
        for (Animator animator : animatorSet.getChildAnimations()) {
            if (animator instanceof ValueAnimator) {
                ValueAnimator valueAnimator = (ValueAnimator) animator;
                if (null != anim.getTypeEvaluator()) {
                    valueAnimator.setEvaluator(anim.getTypeEvaluator());
                }
            } else if (animator instanceof AnimatorSet) {
                initAllAnimTypeEvaluator(anim, (AnimatorSet) animator);
            }
        }
    }

    /**
     * 顺序执行动画集合
     */
    public BaseAnimator playSequentially(BaseAnimator... items) {
        List<Animator> animatorList = getAnimatorList(items);
        if (null != animatorList && animatorList.size() > 0) {
            mAnimatorSet.playSequentially(animatorList);
        }
        return this;
    }

    /**
     * 获取动画插值器
     */
    public Interpolator getInterpolator() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            return (Interpolator) mAnimatorSet.getInterpolator();
        }
        return mInterpolator;
    }

    /**
     * 设置动画插值器
     */
    public BaseAnimator setInterpolator(Interpolator interpolator) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            mInterpolator = interpolator;
        }
        mAnimatorSet.setInterpolator(interpolator);
        return this;
    }

    /**
     * 属性动画计算器，控制动画如何过渡的
     *
     * @param value TypeEvaluator
     * @return BaseAnimator
     */
    public BaseAnimator setTypeEvaluator(TypeEvaluator value) {
        mTypeEvaluator = value;
        return this;
    }

    public TypeEvaluator getTypeEvaluator() {
        return mTypeEvaluator;
    }

    /**
     * 获取动画总耗时
     */
    public long getDuration() {
        return mDuration;
    }

    /**
     * 设置动画时间
     */
    public BaseAnimator setDuration(long duration) {
        mDuration = duration;
        return this;
    }

    /**
     * 获取延时开始的时间
     *
     * @return long
     */
    public long getStartDelay() {
        return mStartDelay;
    }

    /**
     * 设置动画开始延时的时间
     */
    public BaseAnimator setStartDelay(long delay) {
        mStartDelay = delay;
        return this;
    }

    /**
     * 获取执行动画的 view.
     */
    public Object getTarget() {
//        if (mTarget instanceof ITargetView) {
//            return ((ITargetView) mTarget).getView();
//        }
        return null != mTarget ? mTarget.get() : mTarget;
    }

    /**
     * 设置需要动画的view
     */
    public BaseAnimator setTarget(Object target) {
//        mTarget = target;
        mTarget = new WeakReference<>(target);
        // 重置动画，准备动画
        resetTarget();
        prepareAnimSet();
        //
        return this;
    }

//    Object mTarget;
    WeakReference<Object> mTarget; // TODO:优化

    /**
     * 恢复 Target View 的属性.
     */
    public void resetTarget() {
        View view = null;
        Object target = null != mTarget ? mTarget.get() : null;
        if (target instanceof View) {
            view = (View) target;
        } else if (target instanceof ITargetView) {
            view = ((ITargetView) target).getView();
        }
        //
        if (null != view) {
            ViewCompat.setAlpha(view, 1);
            ViewCompat.setScaleX(view, 1);
            ViewCompat.setScaleY(view, 1);
            ViewCompat.setTranslationX(view, 0);
            ViewCompat.setTranslationY(view, 0);
            ViewCompat.setRotation(view, 0);
            ViewCompat.setRotationY(view, 0);
            ViewCompat.setRotationX(view, 0);
        }
    }

    /**
     * 将全部动画ObjectAnim全部设置 重复的属性和次数
     */
    private void setAnimSetAllAnimValues(AnimatorSet animSet) {
        for (Animator animator : animSet.getChildAnimations()) {
            if (animator instanceof ValueAnimator) {
                ValueAnimator valueAnim = (ValueAnimator) animator;
                // 设置重复的次数
                if (mIsTogether) {
                    valueAnim.setRepeatCount(mRepeatCount > 0 ? mRepeatCount - 1 : mRepeatCount);
                }
                // 设置重复的模式
                valueAnim.setRepeatMode(mRepeatMode);
                // 设置属性动画计算器
                if (null != mTypeEvaluator) {
                    valueAnim.setEvaluator(mTypeEvaluator);
                }
            } else if (animator instanceof AnimatorSet) {
                setAnimSetAllAnimValues((AnimatorSet) animator);
            }
        }
    }

    /**
     * 开始动画
     */
    public void startAnim() {
        if (null != mAnimatorSet) {
            // 由于一些公共的参数后，需要对全部子动画递归进行初始化设置.
            // 更多的是一些关于 AnimatorManager 全局的属性设置.
            setAnimSetAllAnimValues(mAnimatorSet);
            // BUG: play-with-after-bfter sequentially 这几种方式连接，对于次数的设置有BUG存在(导致在第一个动画一直跑N次).
            if (!mIsTogether) {
                mAnimatorSet.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (!mIsTogether) {
                            if (mRepeatCount != 0) {
                                mAnimatorSet.start();
                            }
                            // 无限循环
                            if (mRepeatCount == ValueAnimator.INFINITE) {
                                return;
                            }
                            // 判断次数
                            if (mRepeatCount > 1) {
                                mRepeatCount--;
                                return;
                            }
                            // 移除监听
                            mAnimatorSet.removeListener(this);
                        }
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {
                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {
                    }
                });
            }
            //
            if (null != mTarget && null != mTarget.get()) {
                mAnimatorSet.setTarget(mTarget.get());
            }
            if (mStartDelay > 0) {
                mAnimatorSet.setStartDelay(mStartDelay);
            }
            if (mDuration > 0) {
                mAnimatorSet.setDuration(mDuration);
            }
            mAnimatorSet.start();
        }
    }

    /**
     * 取消动画
     */
    public void cancelAnim() {
        if (null != mAnimatorSet) {
            mAnimatorSet.cancel();
        }
    }

    /**
     * 设置重复的次数
     *
     * @param repeatCount 默认为0,ValueAnimator.INFINITE 一直重复，其它数字为动画重复次数
     */
    public BaseAnimator setRepeatCount(int repeatCount) {
        mRepeatCount = repeatCount;
        return this;
    }

    /**
     * 设置循环模式
     *
     * @param repeatMode ValueAnimator.RESTART 表示从头开始 | INFINITE 重复多次 | REVERSE 从末尾倒播
     */
    public BaseAnimator setRepeatMode(int repeatMode) {
        mRepeatMode = repeatMode;
        return this;
    }

    public boolean isRunning() {
        return mAnimatorSet.isRunning();
    }

    public boolean isStarted() {
        return mAnimatorSet.isStarted();
    }

    /**
     * 添加动画事件
     *
     * @param cb
     */
    public void addAnimListener(Animator.AnimatorListener cb) {
        mAnimatorSet.addListener(cb);
    }

    /**
     * 移除某个动画事件
     *
     * @param cb
     */
    public void removeAnimatorListener(Animator.AnimatorListener cb) {
        mAnimatorSet.removeListener(cb);
    }

    /**
     * 移除所有动画事件
     */
    public void removeAllListener() {
        mAnimatorSet.removeAllListeners();
    }

}
